"""
INI文件处理工具类，提供读取、写入、修改INI文件等功能
"""

import os
import configparser
from typing import Dict, List, Any, Optional, Union


class IniUtils:
    """
    INI文件处理工具类，提供各种INI文件操作功能
    """
    
    def __init__(self, ini_path: str = None):
        """
        初始化INI处理工具

        :param ini_path: INI文件路径，可选
        """
        self.config = configparser.ConfigParser()
        self.ini_path = ini_path
        
        if ini_path and os.path.exists(ini_path):
            self.load_ini(ini_path)
    
    def load_ini(self, ini_path: str) -> None:
        """
        加载INI文件

        :param ini_path: INI文件路径
        """
        if not os.path.exists(ini_path):
            raise FileNotFoundError(f"INI文件不存在: {ini_path}")
        
        self.ini_path = ini_path
        self.config.read(ini_path, encoding='utf-8')
    
    def save_ini(self, ini_path: str = None) -> None:
        """
        保存INI文件

        :param ini_path: 保存路径，如果为None则保存到原路径
        """
        if ini_path is None:
            ini_path = self.ini_path
            
        if ini_path is None:
            raise ValueError("未指定保存路径")
        
        with open(ini_path, 'w', encoding='utf-8') as configfile:
            self.config.write(configfile)
    
    def get_all_content(self) -> Dict[str, Dict[str, str]]:
        """
        获取INI文件中所有内容

        :return: 包含所有节和键值对的字典
        """
        all_content = {}
        for section in self.config.sections():
            all_content[section] = {}
            for key in self.config[section]:
                all_content[section][key] = self.config[section][key]
        return all_content
    
    def get_section(self, section: str) -> Dict[str, str]:
        """
        获取指定节的所有内容

        :param section: 节名称
        :return: 指定节的键值对字典
        """
        if not self.config.has_section(section):
            return {}
        return dict(self.config[section])
    
    def get_value(self, section: str, key: str, default: Any = None) -> Any:
        """
        获取指定节和键的值

        :param section: 节名称
        :param key: 键名称
        :param default: 默认值
        :return: 键对应的值，如果不存在则返回默认值
        """
        try:
            return self.config.get(section, key)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return default
    
    def get_int(self, section: str, key: str, default: int = 0) -> int:
        """
        获取指定节和键的整数值

        :param section: 节名称
        :param key: 键名称
        :param default: 默认值
        :return: 键对应的整数值
        """
        try:
            return self.config.getint(section, key)
        except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
            return default
    
    def get_float(self, section: str, key: str, default: float = 0.0) -> float:
        """
        获取指定节和键的浮点数值

        :param section: 节名称
        :param key: 键名称
        :param default: 默认值
        :return: 键对应的浮点数值
        """
        try:
            return self.config.getfloat(section, key)
        except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
            return default
    
    def get_boolean(self, section: str, key: str, default: bool = False) -> bool:
        """
        获取指定节和键的布尔值

        :param section: 节名称
        :param key: 键名称
        :param default: 默认值
        :return: 键对应的布尔值
        """
        try:
            return self.config.getboolean(section, key)
        except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
            return default
    
    def set_value(self, section: str, key: str, value: Any) -> None:
        """
        设置指定节和键的值

        :param section: 节名称
        :param key: 键名称
        :param value: 要设置的值
        """
        if not self.config.has_section(section):
            self.config.add_section(section)
        self.config.set(section, key, str(value))
    
    def add_section(self, section: str) -> bool:
        """
        添加节

        :param section: 节名称
        :return: 是否添加成功
        """
        if not self.config.has_section(section):
            self.config.add_section(section)
            return True
        return False
    
    def remove_section(self, section: str) -> bool:
        """
        删除节

        :param section: 节名称
        :return: 是否删除成功
        """
        return self.config.remove_section(section)
    
    def remove_option(self, section: str, key: str) -> bool:
        """
        删除指定节中的键

        :param section: 节名称
        :param key: 键名称
        :return: 是否删除成功
        """
        if self.config.has_section(section):
            return self.config.remove_option(section, key)
        return False
    
    def has_section(self, section: str) -> bool:
        """
        检查是否存在指定节

        :param section: 节名称
        :return: 是否存在
        """
        return self.config.has_section(section)
    
    def has_option(self, section: str, key: str) -> bool:
        """
        检查指定节中是否存在指定键

        :param section: 节名称
        :param key: 键名称
        :return: 是否存在
        """
        return self.config.has_option(section, key)
    
    def get_sections(self) -> List[str]:
        """
        获取所有节名称

        :return: 节名称列表
        """
        return self.config.sections()
    
    def get_options(self, section: str) -> List[str]:
        """
        获取指定节中的所有键名称

        :param section: 节名称
        :return: 键名称列表
        """
        if self.config.has_section(section):
            return list(self.config[section].keys())
        return []
    
    def clear_section(self, section: str) -> bool:
        """
        清空指定节中的所有键值对

        :param section: 节名称
        :return: 是否清空成功
        """
        if self.config.has_section(section):
            self.config.remove_section(section)
            self.config.add_section(section)
            return True
        return False
    
    def clear_all(self) -> None:
        """
        清空所有内容
        """
        for section in self.config.sections():
            self.config.remove_section(section)
    
    def merge_ini(self, other_ini: Union[str, 'IniUtils']) -> None:
        """
        合并另一个INI文件或IniUtils实例的内容

        :param other_ini: 另一个INI文件路径或IniUtils实例
        """
        if isinstance(other_ini, str):
            # 如果是文件路径
            other_config = configparser.ConfigParser()
            other_config.read(other_ini, encoding='utf-8')
        else:
            # 如果是IniUtils实例
            other_config = other_ini.config
        
        # 合并节和键值对
        for section in other_config.sections():
            if not self.config.has_section(section):
                self.config.add_section(section)
            for key in other_config[section]:
                self.config.set(section, key, other_config[section][key])
    
    def get_ini_info(self) -> Dict[str, Any]:
        """
        获取INI文件信息

        :return: INI文件信息字典
        """
        return {
            'sections_count': len(self.config.sections()),
            'sections': self.config.sections(),
            'file_path': self.ini_path,
            'has_content': len(self.config.sections()) > 0
        }
    
    @staticmethod
    def create_empty_ini(ini_path: str) -> 'IniUtils':
        """
        创建空的INI文件

        :param ini_path: INI文件路径
        :return: IniUtils实例
        """
        ini_utils = IniUtils()
        ini_utils.ini_path = ini_path
        return ini_utils
    
    @staticmethod
    def from_dict(data: Dict[str, Dict[str, Any]]) -> 'IniUtils':
        """
        从字典创建IniUtils实例

        :param data: 包含节和键值对的字典
        :return: IniUtils实例
        """
        ini_utils = IniUtils()
        for section, options in data.items():
            ini_utils.add_section(section)
            for key, value in options.items():
                ini_utils.set_value(section, key, value)
        return ini_utils